/*
 * Copyright 2023-2025, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *   Haiku Development Team
 */

#include <efi/types.h>
#include <efi/system-table.h>
#include <string.h>


// LoongArch64 EFI运行时重定位函数
// 当EFI运行时服务需要重定位时调用此函数
extern "C" efi_status
efi_runtime_relocate(efi_runtime_services *runtime_services, void *data,
	efi_uintn new_offset, efi_uintn old_offset, efi_uintn vd_offset,
	efi_uintn vd_size)
{
	// 计算偏移量差异
	efi_intn offset = new_offset - old_offset;

	// 如果没有偏移量变化，无需重定位
	if (offset == 0)
		return EFI_SUCCESS;

	// 重定位运行时服务表中的函数指针
	runtime_services->GetTime = (void *)((char *)runtime_services->GetTime + offset);
	runtime_services->SetTime = (void *)((char *)runtime_services->SetTime + offset);
	runtime_services->GetWakeupTime = (void *)((char *)runtime_services->GetWakeupTime + offset);
	runtime_services->SetWakeupTime = (void *)((char *)runtime_services->SetWakeupTime + offset);
	runtime_services->SetVirtualAddressMap = (void *)((char *)runtime_services->SetVirtualAddressMap + offset);
	runtime_services->ConvertPointer = (void *)((char *)runtime_services->ConvertPointer + offset);
	runtime_services->GetVariable = (void *)((char *)runtime_services->GetVariable + offset);
	runtime_services->GetNextVariableName = (void *)((char *)runtime_services->GetNextVariableName + offset);
	runtime_services->SetVariable = (void *)((char *)runtime_services->SetVariable + offset);
	runtime_services->GetNextHighMonotonicCount = (void *)((char *)runtime_services->GetNextHighMonotonicCount + offset);
	runtime_services->ResetSystem = (void *)((char *)runtime_services->ResetSystem + offset);

	// EFI 2.0+函数
	if (runtime_services->Hdr.Revision >= EFI_2_00_SYSTEM_TABLE_REVISION) {
		runtime_services->UpdateCapsule = (void *)((char *)runtime_services->UpdateCapsule + offset);
		runtime_services->QueryCapsuleCapabilities = (void *)((char *)runtime_services->QueryCapsuleCapabilities + offset);
		runtime_services->QueryVariableInfo = (void *)((char *)runtime_services->QueryVariableInfo + offset);
	}

	return EFI_SUCCESS;
}